home *** CD-ROM | disk | FTP | other *** search
- /* WIDE AREA INFORMATION SERVER SOFTWARE
- No guarantees or restrictions. See the readme file for the full standard
- disclaimer.
- 5.29.90 Harry Morris, morris@think.com
- */
-
- /* Copyright (c) CNIDR (see ../COPYRIGHT) */
-
-
- #ifndef lint
- static char *RCSid = "$Header: /archives/stelar/src/freeWAIS/freeWAIS-0.2/ir/RCS/sockets.c,v 1.2 93/07/01 19:14:22 warnock Exp $";
- #endif
- typedef struct sockaddr SOCKADDR;
- typedef struct sockaddr_in SOCKADDR_IN;
- /* Change log:
- * $Log: sockets.c,v $
- * Revision 1.2 93/07/01 19:14:22 warnock
- * Fix for gethostname from francois and jonathan
- *
- * Revision 1.1 1993/02/16 15:05:35 freewais
- * Initial revision
- *
- * Revision 1.23 92/05/06 17:34:41 jonathan
- * Added Mach to some compiler switches.
- *
- * Revision 1.22 92/04/28 15:21:14 jonathan
- * Added decoding of IP address to DNS name in accept_client handler.
- *
- * Revision 1.21 92/04/01 09:49:49 morris
- * declared clr_socket static to stop gcc from complaining
- *
- * Revision 1.20 92/03/24 10:35:32 jonathan
- * Put a loop around connect in fd_connect_to_server to check if the connect
- * was interrupted by a system call (usually a timer). Retries if errno is
- * EINTR.
- *
- * Revision 1.19 92/02/16 12:38:22 jonathan
- * Changed bzero's to memset's.
- *
- * Revision 1.18 92/02/16 12:34:11 jonathan
- * Removed code refering to NOINETNTOA, since we should use inet_ntoa.
- *
- * Revision 1.17 92/02/12 13:48:21 jonathan
- * Added "$Log" so RCS will put the log message in the header
- *
- *
- */
-
- /*
- Added code in fd_accept_client_connection to print source Inet address to
- stderr.
- - Jonny G Fri Apr 12 1991
-
- */
-
- #define sockets_c
-
- #include "sockets.h"
-
- #ifdef NOTCPIP /* we don't have TCPIP */
-
- void open_server (port,socket,size) long port; long* socket; long size; {}
- void accept_client_connection (socket,file) long socket; FILE** file; {}
- void close_client_connection (file) FILE* file; {}
- void close_server (socket) long socket; {}
- FILE *connect_to_server (host_name,port) char* host_name; long port;
- {return(NULL);}
- void close_connection_to_server (file) FILE* file; {}
-
- #else /* there is TCPIP */
-
- #include <errno.h>
- #include <string.h>
- #include "panic.h"
-
- #if (defined(ultrix) || defined(BSD) || defined(Mach))
- extern int errno;
- #endif /* ultrix BSD or Mach */
-
- extern char *sys_errlist[];
-
- #ifdef WIN32
- char *bcopy(char*,char*,long);
- #endif
-
- /* XXX
- still need:
- non-blocking modes
- special send/recieve functions? (there are now some in ui.c)
- asynchronous calls?
- */
-
- /* define the number of queued connections allowable on each port */
- #define QUEUE_SIZE 3
-
- #ifndef WIN32
-
- /*---------------------------------------------------------------------------*/
- /* Server functions */
- /*---------------------------------------------------------------------------*/
-
- static boolean clr_socket _AP((struct sockaddr_in *address, long portnumber,
- long* sock));
-
- static boolean clr_socket(address, portnumber, sock)
- struct sockaddr_in *address;
- long portnumber;
- long *sock;
- {
- if (errno == EADDRINUSE) {
- /* Try connecting to it */
- if (connect(*sock, (struct sockaddr*)address, sizeof (struct sockaddr_in)) == 0) {
- close(*sock);
- waislog(WLOG_HIGH, WLOG_ERROR,
- "Cannot bind port %ld: (Address already in use).",
- portnumber);
- waislog(WLOG_HIGH, WLOG_ERROR, "waisserver is already running on this system");
- panic("Exiting");
- } else {
- /* Connection failed; probably socket in FIN_WAIT */
- int one = 1;
-
- (void) close(*sock);
- if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- panic("Open socket failed in trying to clear the port.");
- /*printf("Error binding port %d: (address already in use).\n\
- Attempting to clear stale socket...", portnumber);*/
- if ( setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR,
- (char*)&one, sizeof (one)) < 0) {
- /*printf("Warning: Setsockopt SO_REUSEADDR failed.");*/
- }
- address->sin_family = AF_INET;
- address->sin_addr.s_addr = INADDR_ANY;
-
- address->sin_port = (unsigned short int)htons(portnumber);
-
- /* if (bind(*sock,( SOCKADDR*) address, sizeof(SOCKADDR_IN)) == 0) { */
- if (bind(*sock,(struct sockaddr*) address, sizeof(*address)) == 0) {
- /*printf("Successfully cleared stale EADDRINUSE error");*/
- }
- }
- }
- return(true);
- }
-
-
- void
- open_server(port,fd,size)
- long port;
- long* fd;
- long size;
- { struct sockaddr_in address;
-
- memset(&address, 0, sizeof(address));
-
- /* open the fd */
- if ((*fd = socket(AF_INET,SOCK_STREAM,0)) < 0){
- panic("can't get file descriptor for socket: %s", sys_errlist[errno]);
- }
-
- address.sin_family = AF_INET;
- address.sin_addr.s_addr = htonl(INADDR_ANY);
- address.sin_port = (unsigned short int)htons(port);
- if (bind(*fd,(struct sockaddr*)&address,sizeof(struct sockaddr)) < 0)
- clr_socket(&address, port, fd);
-
- if (listen(*fd,QUEUE_SIZE) < 0)
- panic("can't open server: %s", sys_errlist[errno]);
- }
-
-
-
- /* This is a lower level function provided for use by the lisp version of
- * this library
- * XXX should support non-blocking mode
- */
-
- #include <arpa/inet.h>
-
- void
- fd_accept_client_connection(socket,fd)
- long socket;
- long* fd;
- { /* accept an input connection, and open a file on it */
- struct sockaddr_in source;
- int sourcelen;
- #ifdef BSD
- struct in_addr {
- union {
- struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
- u_long S_addr;
- } S_un;
- } addr_p;
- #endif /* BSD */
-
- sourcelen = sizeof(struct sockaddr_in);
-
- do {
- errno = 0;
- *fd = accept(socket, (struct sockaddr *)&source, &sourcelen);
- } while (*fd < 0 && errno == EINTR);
-
- if(source.sin_family == AF_INET) {
- struct hostent *peer = NULL;
-
- #ifdef __DGUX__
- peer = gethostbyaddr((char *)&source.sin_addr.s_addr, 4, AF_INET);
- #else
- peer = gethostbyaddr((struct sockaddr_in*)&source.sin_addr, 4, AF_INET);
- #endif
-
- if(peer != NULL) {
- waislog(WLOG_MEDIUM, WLOG_CONNECT,
- "Accepted connection from: %s [%s]",
- peer ? peer->h_name : "?",
- #if defined(sparc) && defined(__GNUC__)
- inet_ntoa(&source.sin_addr)
- #else
- inet_ntoa(source.sin_addr)
- #endif /* sparc */
- );
- }
- else {
- waislog(WLOG_MEDIUM, WLOG_CONNECT,
- "Accepted connection from: [%s]",
- #if defined(sparc) && defined(__GNUC__)
- inet_ntoa(&source.sin_addr)
- #else
- inet_ntoa(source.sin_addr)
- #endif /* sparc */
- );
- }
- }
- if (*fd < 0)
- panic("can't accept connection");
- }
-
-
- /* This is the prefered C function for accepting client requests */
- void
- accept_client_connection(socket,file)
- long socket;
- FILE** file;
- { long fd; /* file descriptor actually used */
- fd_accept_client_connection(socket,&fd);
- if ((*file = fdopen(fd,"r+")) == NULL)
- panic("can't accept connection");
- }
-
- /* When a server wants to end the session with a client */
- void
- close_client_connection(file)
- FILE* file;
- {
- fclose(file);
- }
-
- /* when exiting the top level server process (not the forked
- server processes that come one per client).
- Maybe we need to do this once per client as well.
- */
- void
- close_server(socket)
- long socket;
- {
- close(socket);
- }
-
- #endif /* !WIN32 */
-
- /*---------------------------------------------------------------------------*/
- /* Client functions */
- /*---------------------------------------------------------------------------*/
-
- /* This is a lower level function provided for use by the lisp version of
- * this library
- * XXX should support non-blocking mode
- */
-
- #define HOSTNAME_BUFFER_SIZE 120
- #define MAX_RETRYS 10
-
- boolean
- fd_connect_to_server(host_name,port,fd)
- char* host_name;
- long port;
- long* fd;
- {
- char hostnamebuf[80];
- long rc, i;
- struct hostent *host;
- /* struct servent *service = NULL; not used */
- struct sockaddr_in name;
-
- memset((char *)&name, 0,sizeof (name));
-
- #ifdef __DGUX__
- name.sin_addr = inet_addr(host_name);
- #else
- name.sin_addr.s_addr = inet_addr(host_name);
- #endif
-
- if (name.sin_addr.s_addr != -1) {
- name.sin_family = AF_INET;
- (void) strcpy(hostnamebuf, host_name);
- }
- else {
- host = gethostbyname(host_name);
-
- if(NULL == host){
- return FALSE;
- }
-
- name.sin_family = host->h_addrtype;
- #ifdef h_addr
- #ifdef WIN32
- bcopy(host->h_addr_list[0],
- (char *)&name.sin_addr, host->h_length);
- #else
- bcopy(host->h_addr_list[0],
- (caddr_t)&name.sin_addr, host->h_length);
- #endif
- #endif
- (void) strcpy(hostnamebuf, host->h_name);
- }
- host_name = hostnamebuf;
-
- #ifdef WIN32
- name.sin_port = (unsigned short int)htons((u_short)port);
- #else
- name.sin_port = (unsigned short int)htons(port);
- #endif
-
- *fd = socket (AF_INET, SOCK_STREAM, 0);
- for(i = 0; i < MAX_RETRYS; i++) {
- rc = connect (*fd, (struct sockaddr *)&name, sizeof (name));
- if(rc == 0) return TRUE;
- else if(errno == EINTR){
- #ifdef WIN32
- Sleep(1000); /* WIN32's sleep has an unit in millisec */
- #else
- sleep(1);
- #endif
- }
- else {
- perror("Connect to socket did not work (1)");
- return FALSE;
- }
- }
- return FALSE;
- }
-
- /* This is the prefered C function for initiating client requests */
- FILE *
- connect_to_server(host_name,port)
- char* host_name;
- long port;
- {
- FILE* file;
- long fd;
- if(fd_connect_to_server(host_name,port,&fd) == FALSE) {
- perror("Connect to socket did not work (2)");
- return NULL;
- }
-
- if ((file = fdopen(fd,"r+")) == NULL) {
- perror("Connect to socket did not work (3)");
- return NULL;
- }
-
- return file;
- }
-
- void
- close_connection_to_server(file)
- FILE* file;
- {
- fclose(file);
- }
-
- /*---------------------------------------------------------------------------*/
-
- #endif /* there is TCPIP */
-
- #ifndef WIN32
-
- /* Francois and Jonathan Goldman - hostname fix */
- char *
- mygethostname(hostname, len)
- char *hostname;
- long len;
- {
- char name[255];
- struct hostent *h;
-
- gethostname(name, 254);
- strcpy(hostname,name);
-
- h = gethostbyname(name);
-
- if ( (h = gethostbyname(name)) != NULL) {
- if ( (strlen(h->h_name) >= len) && ( len > 0 ) ) {
- strncpy(hostname, h->h_name,len-1);
- }
- else {
- strcpy(hostname, h->h_name);
- }
- }
- else {
- if ( ( strlen(name) >= len) && (len > 0 ) ) {
- strncpy(hostname, name, len-1);
- }
- else {
- strcpy(hostname, name);
- }
- }
-
- return(hostname);
- }
-
- #endif /* !WIN32 */
-